package com.ledi.guns.core.shiro;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.ledi.guns.common.persistence.model.User;
import com.ledi.guns.core.redis.KeyValueDAO;
import com.ledi.guns.core.shiro.factory.IShiro;
import com.ledi.guns.core.shiro.factory.ShiroFactroy;
import com.ledi.guns.core.util.SystemConstans;
import com.ledi.guns.core.util.ToolUtil;

@Component
public class ShiroDbRealm extends AuthorizingRealm {

	private final static Logger logger = LoggerFactory.getLogger(ShiroDbRealm.class);

	@Autowired
	private KeyValueDAO keyValueDAO;

	/**
	 * 登录认证
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {

		IShiro shiroFactory = ShiroFactroy.me();
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		User user = shiroFactory.user(token.getUsername());
		ShiroUser shiroUser = shiroFactory.shiroUser(user);
		SimpleAuthenticationInfo info = shiroFactory.info(shiroUser, user, super.getName());

		// 获取当前用户的信息
		Subject subject = SecurityUtils.getSubject();
		// 处理session
		DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
		DefaultWebSessionManager sessionManager = (DefaultWebSessionManager) securityManager.getSessionManager();
		SessionDAO sessionDAO = sessionManager.getSessionDAO();
		Collection<Session> sessions = sessionDAO.getActiveSessions();// 获取当前已登录的用户session列表
		for (Session session : sessions) {
			SimplePrincipalCollection spc = (SimplePrincipalCollection)
					session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
			if (spc != null) {
				ShiroUser sUser = (ShiroUser) spc.getPrimaryPrincipal();
				// 踢出除当前session之外的所有当前用户的session
				if (token.getUsername().equals(String.valueOf(sUser.getAccount())) &&
						!subject.getSession().getId().equals(session.getId())) {
					logger.info("踢出之前登录的账号：{}", sUser.getAccount());
					logger.info("踢出之前登录的sessionId：{}", session.getId());
					// sessionDAO.delete(session);
					keyValueDAO.set(SystemConstans.USER_ACOUNT_SESSIONID.replaceAll("\\{0\\}", sUser.getAccount()), session.getId() + "", 0);
				}
			}
		}

		return info;
	}

	/**
	 * 权限认证
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

		IShiro shiroFactory = ShiroFactroy.me();
		ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
		List<Integer> roleList = shiroUser.getRoleList();

		Set<String> permissionSet = new HashSet<>();
		Set<String> roleNameSet = new HashSet<>();

		for (Integer roleId : roleList) {
			List<String> permissions = shiroFactory.findPermissionsByRoleId(roleId);
			if (permissions != null) {
				for (String permission : permissions) {
					if (ToolUtil.isNotEmpty(permission)) {
						permissionSet.add(permission);
					}
				}
			}
			String roleName = shiroFactory.findRoleNameByRoleId(roleId);
			roleNameSet.add(roleName);
		}

		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.addStringPermissions(permissionSet);
		info.addRoles(roleNameSet);
		return info;
	}

	// /**
	// * 璁剧疆璁よ瘉鍔犲瘑鏂瑰紡
	// */
	// @Override
	// public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
	//
	// HashedCredentialsMatcher md5CredentialsMatcher = new HashedCredentialsMatcher();
	// md5CredentialsMatcher.setHashAlgorithmName(ShiroKit.hashAlgorithmName);
	// md5CredentialsMatcher.setHashIterations(ShiroKit.hashIterations);
	// super.setCredentialsMatcher(md5CredentialsMatcher);
	// }

}
